package com.yang.moyu.meta.framework.shiro.service.impl;

import com.yang.moyu.meta.config.properties.JwtProperties;
import com.yang.moyu.meta.framework.shiro.jwt.JwtToken;
import com.yang.moyu.meta.framework.shiro.service.LoginRedisService;
import com.yang.moyu.meta.framework.shiro.service.ShiroLoginService;
import com.yang.moyu.meta.framework.shiro.util.JwtUtil;
import com.yang.moyu.meta.framework.util.JwtTokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Date;

/**
 * Create by 10296 on 2021/12/16
 *
 * @Description:
 */
@Service
public class ShiroLoginServiceImpl implements ShiroLoginService {

    private Logger logger = LoggerFactory.getLogger(ShiroLoginServiceImpl.class);

    @Autowired
    private LoginRedisService loginRedisService;

    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void refreshToken(JwtToken jwtToken, HttpServletResponse httpServletResponse) throws Exception {
        if (jwtToken == null) {
            return;
        }
        String token = jwtToken.getToken();
        if (StringUtils.isEmpty(token)) {
            return;
        }
        /*判断是否刷新token*/
        boolean isRefreshToken = jwtProperties.isRefreshToken();
        if (!isRefreshToken) {
            return;
        }
        /*获取过期时间*/
        Date expireDate = JwtUtil.getExpireDate(token);
        /*获取倒计时*/
        Integer countDown = jwtProperties.getRefreshTokenCountDown();

        /*如果(当前时间+倒计时)>过期时间，则刷新token*/
        boolean refresh = DateUtils.addSeconds(new Date(), countDown).after(expireDate);
        if (!refresh) {
            return;
        }
        /*如果token继续发往后台，则提示，此token已失效，请使用新的token，错误码*/
        boolean exists = loginRedisService.exists(token);
        if (!exists) {
            httpServletResponse.setStatus(461);
            throw new AuthenticationException("token已失效，请使用新的token");

        }
        String username = jwtToken.getUsername();
        String salt = jwtToken.getSalt();
        Long expireSecond = jwtProperties.getExpireSecond();
        String newToken = JwtUtil.generateToken(username, salt, Duration.ofSeconds(expireSecond));
        //生成新JwtToken
        JwtToken newJwtToken = JwtToken.build(newToken, username, newToken, expireSecond);
        //更新redis缓存
        loginRedisService.refreshLoginInfo(token, username, newJwtToken);
        logger.info("刷新token成功，原token:{},新token:{}", token, newToken);
        //设置响应头
        //刷新token
        httpServletResponse.setStatus(460);
        httpServletResponse.setHeader(JwtTokenUtil.getTokenName(), newToken);
    }
}

